//package miniparser;
//import minijava.*;
//import java.util.*;
//import System.IO.*;

public class SyntaxTreeGenerator : MinijavaVisitor, Constants {
    TextWriter writer;
    public SyntaxTreeGenerator(String filename) {
        try {
            writer = new StreamWriter(filename + ".mp");
        }
        catch (IOException ioe) {
            Console.WriteLine(ioe);
        }
    }
    public void flush() {
        writer.Flush();
        writer.Close();
    }
    public bool preVisit(Program p) {
        writer.WriteLine("prologues:=3;");
        writer.WriteLine("verbatimtex");
        writer.WriteLine("%&latex");
        writer.WriteLine("\\documentclass{article}");
        writer.WriteLine("\\usepackage{graphics}");
        writer.WriteLine("\\usepackage{color}");
        writer.WriteLine("\\definecolor{dgreen}{rgb}{0.1,0.5,0.1}");
        writer.WriteLine("\\begin{document}");
        writer.WriteLine("etex");
        writer.WriteLine("input boxes;");
        writer.WriteLine("input trees;");
        writer.WriteLine("beginfig(1);");

        writer.WriteLine("interim levelsep:=80pt;");
        writer.WriteLine("interim treesep:=-2pt;");

        writer.WriteLine("tree.root(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}program}} etex)(");
        p.ld[0].accept(this);
        for (int i = 1; i < p.ld.Count; i++) {
            writer.Write(",");
            p.ld[i].accept(this);
        }
        writer.Write(",");
        p.ls[0].accept(this);
        for (int i = 1; i < p.ls.Count; i++) {
            writer.Write(",");
            p.ls[i].accept(this);
        }
        writer.WriteLine(");");
        writer.WriteLine("drawtrees(root);");
        writer.WriteLine("endfig;");
        writer.WriteLine("end;");
        return false;
    }
    public bool preVisit(Decl d) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}decl}} etex)(");
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}type}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} int} etex))\n");
        writer.WriteLine(",tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}name}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + d.varlist[0] + "} etex))");
        for (int i = 1; i < d.varlist.Count; i++)
            writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} ,} etex),tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}name}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + d.varlist[i] + "} etex))");
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} ;} etex))");
        return true;
    }
    public bool preVisit(Stmt.Assign a) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}stmt}} etex)(");
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}name}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + a.lhs + "} etex)),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} =} etex),");
        return true;
    }
    public void postVisit(Stmt.Assign a) {
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} ;} etex))");
    }
    public bool preVisit(Expr.Priority p) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}expr}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $($} etex),");
        p.e.accept(this);
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $)$} etex))");
        return false;
    }
    public bool preVisit(Cond.Priority p) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}cond}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $($} etex),");
        p.c.accept(this);
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $)$} etex))");
        return false;
    }
    public bool preVisit(Expr.Binex i) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}expr}} etex)(");
        i.e1.accept(this);
        String @operator = null;
        if (i.op == PLUS) @operator = "+";
        if (i.op == MINUS) @operator = "-";
        if (i.op == MULT) @operator = "*";
        if (i.op == DIV) @operator = "/";
        if (i.op == MOD) @operator = "\\%";
        writer.WriteLine(",tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}binop}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + @operator + "} etex)),");
        i.e2.accept(this);
        writer.WriteLine(")");
        return false;
    }
    public void visit(Expr.Identifier d) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}expr}} etex)(tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}name}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + d.i + "} etex)))");
    }
    public void visit(Expr.IntConst d) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}expr}} etex)(tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}number}} etex)");
        writer.WriteLine("(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + d.i + "} etex)))");
    }
    public bool preVisit(Stmt.Compound c) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}stmt}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $\\{$} etex)");
        for (int i = 0; i < c.ls.Count; i++) {
            writer.Write(",");
            c.ls[i].accept(this);
        }
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $\\}$} etex))");
        return false;
    }
    public bool preVisit(Stmt.IfThenElse i) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}stmt}} etex)(");
        writer.WriteLine("leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} if} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $($} etex),");
        i.cond.accept(this);
        //writer.WriteLine("leaf(btex \\tt BED etex)");
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $)$} etex),");
        i.then.accept(this);
        if (i.els != null) {
            writer.WriteLine(",leaf(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}else}} etex),");
            i.els.accept(this);
        }
        writer.WriteLine(")");
        return false;
    }
    public bool preVisit(Stmt.Loop l) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}stmt}} etex)(");
        writer.WriteLine("leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} while} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $($} etex),");
        l.cond.accept(this);
        //writer.WriteLine("leaf(btex \\tt BED etex)");
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $)$} etex),");
        l.body.accept(this);
        writer.WriteLine(")");
        return false;
    }
    public bool preVisit(Stmt.Write i) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}stmt}} etex)(");
        writer.WriteLine("leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} write} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $($} etex),");
        if (i.e != null) i.e.accept(this);
        writer.WriteLine(",leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $)$} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} ;} etex))");
        return false;
    }
    public void visit(Stmt.Read i) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}stmt}} etex)(");
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}name}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + i.lhs + "} etex)),");
        writer.WriteLine("leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} =} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} read} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $($} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} $)$} etex),leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} ;} etex))");
    }
    public bool preVisit(Cond.BinCond c) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}cond}} etex)(");
        c.e1.accept(this);
        String @operator = null;
        if (c.op == LEQ) @operator = "<=";
        if (c.op == GTQ) @operator = ">=";
        if (c.op == GT) @operator = ">";
        if (c.op == LE) @operator = "<";
        if (c.op == NEQ) @operator = "!=";
        if (c.op == EQ) @operator = "==";
        writer.WriteLine(",tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}comp}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + @operator + "} etex)),");
        c.e2.accept(this);
        writer.WriteLine(")");
        return false;
    }
    public bool preVisit(Cond.BBinCond c) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}cond}} etex)(");
        c.c1.accept(this);
        String @operator = null;
        if (c.op == Constants.AND) @operator = "\\&\\&";
        if (c.op == Constants.OR) @operator = "||";
        writer.WriteLine(",tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}bbinop}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} " + @operator + "} etex)),");
        c.c2.accept(this);
        writer.WriteLine(")");
        return false;
    }
    public bool preVisit(Expr.Unex i) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}expr}} etex)(tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}unop}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} -} etex)),");
        i.e1.accept(this);
        writer.WriteLine(")");
        return false;
    }
    public bool preVisit(Cond.BUnOp i) {
        writer.WriteLine("tree(btex \\fcolorbox{blue}{white}{\\tt {\\color{dgreen}bunop}} etex)(leaf(btex \\fcolorbox{red}{white}{\\phantom{!g}\\tt\\hspace{-1.2em} !} etex),");
        i.c.accept(this);
        writer.WriteLine(")");
        return false;
    }

}
